package com.tmall.testgen.client.runinspring.push.jmx;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
//import org.springframework.web.context.support.XmlWebApplicationContext;

/**
 * @author haojia
 * @date 2014-07-04
 */
public class ConfigExtractor {

	public static List<DBInfoForJmx>  getDB(Object webApplicationContext){
		List<DBInfoForJmx>result=new ArrayList<DBInfoForJmx>();
		
		try {
			result.addAll(extractDBInfoInTDDL(webApplicationContext));
		} catch (Exception e) {
			//e.printStackTrace();
		}
		
		try {
			result.addAll(extractDBInfoInBasic(webApplicationContext));
			
		} catch (Exception e) {
		}
		
		return  result;
	}
	
	private static List<DBInfoForJmx> extractDBInfoInBasic(Object webApplicationContext) throws Exception{
		
		
		List<DBInfoForJmx>result=new ArrayList<DBInfoForJmx>();
		
		Method  getBeansOfTypeMethod = webApplicationContext.getClass().getMethod("getBeansOfType", Class.class);
		
		Class basicDataSourceClass= Class.forName("org.apache.commons.dbcp.BasicDataSource");
		Object dataSourceObjs=getBeansOfTypeMethod.invoke(webApplicationContext, basicDataSourceClass);
		
		if(dataSourceObjs!=null&&dataSourceObjs instanceof Map){
			Map<String,Object> dataSourceMap=(Map<String, Object>) dataSourceObjs;
			for(String beanName:dataSourceMap.keySet()){
				Object dataSource=dataSourceMap.get(beanName);
				
				
				DBInfoForJmx info=new DBInfoForJmx(); 
				
				Method getUrl=basicDataSourceClass.getMethod("getUrl");
				info.setUrl((String) getUrl.invoke(dataSource));
				
				Method getUsername=basicDataSourceClass.getMethod("getUsername");
				info.setUserName((String) getUsername.invoke(dataSource));
				
				Method getPassword=basicDataSourceClass.getMethod("getPassword");
				info.setPassword((String) getPassword.invoke(dataSource));
				
				Method getDriverClassName=basicDataSourceClass.getMethod("getDriverClassName");
				info.setDriverClass((String) getDriverClassName.invoke(dataSource));
				
				result.add(info);
			}
		}
		return result;
	}
	
	
    private static  List<DBInfoForJmx> extractDBInfoInTDDL(Object webApplicationContext) throws Exception{
        List<DBInfoForJmx>result=new ArrayList<DBInfoForJmx>();
        
        
        Method  getBeansOfTypeMethod = webApplicationContext.getClass().getMethod("getBeansOfType", Class.class);
        
        Object dataGroupObjs=getBeansOfTypeMethod.invoke(webApplicationContext, Class.forName("com.taobao.tddl.jdbc.group.TGroupDataSource"));
        
        if(dataGroupObjs!=null&&dataGroupObjs instanceof Map){
            Map<String,Object> dataGroupMap=(Map<String, Object>) dataGroupObjs;
            for(String beanName:dataGroupMap.keySet()){
                Object tGroupDataSource=dataGroupMap.get(beanName);
                
                Field configManagerField=tGroupDataSource.getClass().getDeclaredField("configManager");
                configManagerField.setAccessible(true);
                Object configManagerValue=configManagerField.get(tGroupDataSource);
                
                
                Field dataSourceWrapperMapField=configManagerValue.getClass().getDeclaredField("dataSourceWrapperMap");
                dataSourceWrapperMapField.setAccessible(true);
                Object dataSourceWrapperMapValue=dataSourceWrapperMapField.get(configManagerValue);
                
                //========
                Field writeDBSelectorWrapperField=configManagerValue.getClass().getDeclaredField("writeDBSelectorWrapper");
                writeDBSelectorWrapperField.setAccessible(true);
                Object writeDBSelectorWrapperValue=writeDBSelectorWrapperField.get(configManagerValue);
                
                Field dataSourceMapField=writeDBSelectorWrapperValue.getClass().getDeclaredField("dataSourceMap");
                dataSourceMapField.setAccessible(true);
                Map<Object,Object> dataSourceMapValue=(Map<Object, Object>) dataSourceMapField.get(writeDBSelectorWrapperValue);
                
                
                
                for(Object key:dataSourceMapValue.keySet()){
                    Object value=dataSourceMapValue.get(key);
                    Field dswField=value.getClass().getField("dsw");
                    Object dswValue=dswField.get(value);
                    
                    //判断是否有效===
                    Field weightField=dswValue.getClass().getDeclaredField("weight");
                    weightField.setAccessible(true);
                    Object weightValue=weightField.get(dswValue);
                    
                    Field wField=weightValue.getClass().getDeclaredField("w");
                    wField.setAccessible(true);
                    int wValue=(Integer) wField.get(weightValue);
                    if(wValue<=0)
                        continue;
                    //===============
                    Field wrappedDataSourceField=dswValue.getClass().getDeclaredField("wrappedDataSource");
                    wrappedDataSourceField.setAccessible(true);
                    Object wrappedDataSourceValue=wrappedDataSourceField.get(dswValue);
                    
                    Field dsConfHandleField=wrappedDataSourceValue.getClass().getDeclaredField("dsConfHandle");
                    dsConfHandleField.setAccessible(true);
                    Object dsConfHandleValue=dsConfHandleField.get(wrappedDataSourceValue);
                    try{
                    Field druidDataSourceField=dsConfHandleValue.getClass().getDeclaredField("druidDataSource");
                    druidDataSourceField.setAccessible(true);
                    Object druidDataSourceValue=druidDataSourceField.get(dsConfHandleValue);
                    
                        
                    Class druidClass=Class.forName("com.alibaba.druid.pool.DruidAbstractDataSource");
                    Field jdbcUrlField=druidClass.getDeclaredField("jdbcUrl");
                    jdbcUrlField.setAccessible(true);
                    String jdbcUrl=jdbcUrlField.get(druidDataSourceValue).toString();
                    
                    Field driverClassField=druidClass.getDeclaredField("driverClass");
                    driverClassField.setAccessible(true);
                    String driverClass=driverClassField.get(druidDataSourceValue).toString();
                    
                    
                    
                    Field usernameField=druidClass.getDeclaredField("username");
                    usernameField.setAccessible(true);
                    String username=usernameField.get(druidDataSourceValue).toString();
                    
                    Field passwordField=druidClass.getDeclaredField("password");
                    passwordField.setAccessible(true);
                    String password=passwordField.get(druidDataSourceValue).toString();
                    
                    DBInfoForJmx info=new DBInfoForJmx();
                    info.setUrl(jdbcUrl);
                    info.setUserName(username);
                    info.setPassword(password);
                    info.setDriverClass(driverClass);
                    result.add(info);
                    }catch(Exception e){
                       Field tAtomDsConfDOField= dsConfHandleValue.getClass().getDeclaredField("runTimeConf");
                       tAtomDsConfDOField.setAccessible(true);
                       Object tAtomDsConfDOValue=tAtomDsConfDOField.get(dsConfHandleValue);
                       
                       Field dbNameField=tAtomDsConfDOValue.getClass().getDeclaredField("dbName");
                       dbNameField.setAccessible(true);
                       String dbName=dbNameField.get(tAtomDsConfDOValue).toString();
                       
                       
                       Field ipField=tAtomDsConfDOValue.getClass().getDeclaredField("ip");
                       ipField.setAccessible(true);
                       String ip=ipField.get(tAtomDsConfDOValue).toString();
                       
                       Field portField=tAtomDsConfDOValue.getClass().getDeclaredField("port");
                       portField.setAccessible(true);
                       String port=portField.get(tAtomDsConfDOValue).toString();
                       
                       
                       String jdbcUrl="jdbc:mysql://"+ip+":"+port+"/"+dbName;
                        
                        
                        Field usernameField=tAtomDsConfDOValue.getClass().getDeclaredField("userName");
                        usernameField.setAccessible(true);
                        String username=usernameField.get(tAtomDsConfDOValue).toString();
                        
                        Field passwordField=tAtomDsConfDOValue.getClass().getDeclaredField("passwd");
                        passwordField.setAccessible(true);
                        String password=passwordField.get(tAtomDsConfDOValue).toString();
                        
                        DBInfoForJmx info=new DBInfoForJmx();
                        info.setUrl(jdbcUrl);
                        info.setUserName(username);
                        info.setPassword(password);
                        info.setDriverClass("com.mysql.jdbc.Driver");
                        result.add(info);
                    }
                    
                    
                    
                }
            }
        }
        return result;
    }
    
	
}
